package com.wn.cl.park.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wn.cl.park.mapper.OrderMapper;
import com.wn.cl.park.mapper.ParkingSpotsMapper;
import com.wn.cl.park.mapper.PaymentsMapper;
import com.wn.cl.park.mapper.ReservationsMapper;
import com.wn.cl.park.model.dto.NowReserveDto;
import com.wn.cl.park.model.entity.Order;
import com.wn.cl.park.model.entity.ParkingSpots;
import com.wn.cl.park.model.entity.Reservations;
import com.wn.cl.park.model.enums.DmhStatus;
import com.wn.cl.park.model.enums.DmhStatusString;
import com.wn.cl.park.service.IReservationsService;
import com.wn.sddfp.common.exception.Assert;
import com.wn.sddfp.common.result.enums.impl.BusinessCode;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author yellow docker
 * @since 2025-03-11
 */
@Service
public class ReservationsServiceImpl extends ServiceImpl<ReservationsMapper, Reservations> implements IReservationsService {
    @Autowired
    private ParkingSpotsMapper parkingSpotsMapper;

    @Autowired
    private PaymentsMapper paymentsMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private RedisTemplate redisTemplate;
    //预约停车位
    @Override
    @Transactional
    public void ReservePark(NowReserveDto reserveDto) {
        //计数器统计取消次数
        String key = DmhStatusString.OVERDUE.getConstant()+reserveDto.getUserId();
        Integer timeoutCount = (Integer) redisTemplate.opsForValue().get(key);
        Assert.error(ObjectUtil.isNotNull(timeoutCount) && timeoutCount>=3, BusinessCode.OVERDUE_MAX_TIMES);
        //当存在未支付订单时，不允许预定
        Reservations reservationsTemp = baseMapper.selectOne(Wrappers.lambdaQuery(Reservations.class).eq(Reservations::getUserId, reserveDto.getUserId())
                .eq(Reservations::getStatus, DmhStatus.RESERVATIONS_LOCK.getCode()));
        Assert.error(ObjectUtil.isNotNull(reservationsTemp), BusinessCode.RESERVATIONS_ALREADY_EXISTS);


        //查询空闲车位
        ParkingSpots parkingSpots = parkingSpotsMapper.selectOne(Wrappers.lambdaQuery(ParkingSpots.class)
                .eq(ParkingSpots::getStatus, 0)
                .eq(ParkingSpots::getParkingLotId, 1).last("LIMIT 1")
        );
        Assert.error(ObjectUtil.isNull(parkingSpots), BusinessCode.PARKING_LOT_IS_FULL);
        //更新车位状态
        parkingSpots.setStatus(DmhStatus.SPOT_LOCK.getCode());
        parkingSpotsMapper.updateById(parkingSpots);

        //创建订单表
        Order order = new Order();
        Long tempOrderId = IdUtil.getSnowflake(1, 1).nextId();
        String tempOrderNum = "TC-" + tempOrderId;
        order.setId(tempOrderId);
        order.setOrderNum(tempOrderNum);
        order.setTotalPrice(reserveDto.getPayment());
        order.setUserId(Long.valueOf(reserveDto.getUserId()));
        order.setState(DmhStatus.ORDER_PAYING.getCode());
        orderMapper.insert(order);

        //创建预约记录
        Reservations reservations = new Reservations();
        reservations.setOrderId(tempOrderId);
        reservations.setUserId(Long.valueOf(reserveDto.getUserId()));
        reservations.setLicensePlate(reserveDto.getLicensePlate());
        reservations.setParkingSpotId(parkingSpots.getId());
        reservations.setStatus(DmhStatus.RESERVATIONS_LOCK.getCode());
        reservations.setAmount(reserveDto.getPayment());
        baseMapper.insert(reservations);


        rabbitTemplate.convertAndSend(
                "delayed-exchange",  // 交换机名称
                "unpaid.delay",         // 路由键
                reservations.getId(),            // 消息体（订单ID）
                message -> {
                    // 设置延迟时间：5分钟（300,000毫秒）
                    message.getMessageProperties().setHeader("x-delay", 300000);
                    return message;
                });

    }


}
